; ** por compatibilidad se omiten tildes **
; ==============================================================================
; TRABAJO PRACTICO 3 - System Programming - ORGANIZACION DE COMPUTADOR II - FCEN
; ==============================================================================

%include "imprimir.mac"
%define KERNEL_PAGE_DIR			0x00021000
%define KERNEL_PAGE_TABLE		0x00022000

%define KERNEL_PAGE_DIR			0x00021000 ;/* direccion fisica para el directorio de paginas del kernel */
%define KERNEL_PAGE_TABLE		0x00022000 ;/* direccion fisica para la tabla de paginas del kernel */

global start
global test_paging
;global print_asm


;; GDT
extern GDT_DESC

;; IDT
extern IDT_DESC
extern idt_inicializar

extern mmu_inicializar
extern tss_inicializar
extern sched_inicializar

;; PIC
extern resetear_pic
extern habilitar_pic
extern deshabilitar_pic

;; Saltear seccion de datos
jmp start

;;
;; Seccion de datos.
;;
iniciando_mr_msg db		'Iniciando kernel (Modo Real)...'
iniciando_mr_len equ	$ - iniciando_mr_msg

iniciando_mp_msg db		'Iniciando kernel (Modo Protegido)...'
iniciando_mp_len equ	$ - iniciando_mp_msg

offset : dd 0
selector: dw 0
;;
;; Seccion de código.
;;

;; Punto de entrada del kernel.
BITS 16
start:
	; Deshabilitar interrupciones
	cli

	; Imprimir mensaje de bienvenida
	imprimir_texto_mr iniciando_mr_msg, iniciando_mr_len, 0x07, 0, 0

	; habilitar A20
	call habilitar_A20
	
	; dehsabilitar las interrupciones

	; cargar la GDT

	lgdt [GDT_DESC]

	; setear el bit PE del registro CR0

	mov eax, cr0
	or eax, 1
	mov cr0, eax


	; pasar a modo protegido

	jmp 0x8:modoProtegido 			; saltamos a modo protegido

BITS 32
	modoProtegido:
	; acomodar los segmentos
	xor eax, eax
	mov ax, 10000b   ;Selector { index: 2; gdt(0)/ldt(1): 0 ; rpl:00}
	mov ds, ax       ; data segment
	mov ss, ax
	mov es, ax
	mov gs, ax
	mov ax, 111000b	; cargo el selector del segmento de video
	mov fs, ax

	imprimir_texto_mp iniciando_mp_msg, iniciando_mp_len, 0x07, 0, 0


	; seteo la pila
 	mov ebp, 0x20000
 	mov esp, ebp 


	; pintar pantalla, todos los colores, que bonito!

	xor ebx, ebx
	xor ax, ax
limpiar_pantalla:
	mov [fs:ebx*2], ax
	inc ebx
	cmp ebx, 2000
	jb limpiar_pantalla
	
	
	; imprimos en la primera linea
	mov ecx, msg_primera_linea_len   	; tamano del texto a imprimir
	mov bh, 0x0F            		; todo en fondo verde azulado y letras blancas
	xor esi, esi

write_prim_linea:
	mov bl, [ds:msg_primera_linea + esi]	
	mov [fs:esi*2], bx
	inc esi
	loop write_prim_linea


	; imprimos en la ultima linea
	mov edi, 3840				; 3840 : ultima linea de la pantalla	
	mov ecx, msg_ultima_linea_len   	; tamano del texto a imprimir
	mov bh, 0x0F            		; todo en fondo verde azulado y letras blancas
	xor esi, esi

write_ult_linea:
	mov bl, [ds:msg_ultima_linea + esi]	
	mov [fs:edi + esi*2], bx
	inc esi
	loop write_ult_linea



	; inicializar el manejador de memoria

	

	; inicializar el directorio de paginas
	xor ecx, ecx
	mov ebx, KERNEL_PAGE_DIR
	.pageDirectory:
			cmp ecx, 1024
			je .finPageDirectory
			mov dword [ebx + ecx * 4 - 4], 0x00000002
			inc ecx
			jmp .pageDirectory
			.finPageDirectory:

	mov dword [KERNEL_PAGE_DIR], KERNEL_PAGE_TABLE + 0x3
	;supervisor, read/write, present

	xor ecx, ecx
	mov ebx, KERNEL_PAGE_TABLE
	mov edx, 0x0000					; direccion base para cada pagina (recordar que las primeras son identity maping)
	.pageTable:
		cmp ecx, 0x164 ;(reemplazar por este valor en hexa)	; identity mapping para las primeras (0x163FFF / 0x163FFF) paginas
		je .finPageTable
		mov [ebx + ecx * 4 ], edx
		add dword [ebx + ecx * 4 ], 0x00000003	; permisos de supervisor = 0, r/w = 1, present = 1
		add edx, 0x1000					; sumamos 0x1000 para avanzar a la prox pagina
		inc ecx
		jmp .pageTable
		.finPageTable:

	mov dword [ebx + 0x3a0 * 4], 0x10003

	imprimir_texto_mp msg_primera_linea_paging, msg_primera_linea_paging_len, 0x07, 0, 0

	; inicializar memoria de tareas
	call mmu_inicializar

	; habilitar paginacion

		mov eax, KERNEL_PAGE_DIR
		mov cr3, eax
		mov eax, cr0
		or eax, 0x80000000 ;habilitamos paginacion
		

		mov cr0, eax

	; inicializar tarea idle

	; inicializar todas las tsss
    call tss_inicializar

	; inicializar entradas de la gdt de tss

	; inicializar el scheduler
    call sched_inicializar

	; inicializar la IDT
	call idt_inicializar
	lidt [IDT_DESC]
	
	; configurar controlador de interrupciones
	call deshabilitar_pic
	call resetear_pic
	call habilitar_pic

	sti

	; cargo la primer tarea null

	mov ax, 0x40			; 0x40 = (TAREA_INICIAL_INDEX << 3) + DPL
	ltr ax

	; aca salto a la primer tarea
    
    ; pruebo cr3 de arbitro
    ;mov eax, 0x34000
    ;mov cr3, eax
    
    
	jmp 0x48:0			; salto a tarea IDLE
	;jmp 0x50:0			; salto a tarea 1
    ;jmp 0x70:0          ; salto a arbitro

	; dividimos por cero
	;xor eax, eax
	;div eax
	


	; Ciclar infinitamente (por si algo sale mal)
	jmp $


test_paging:
	; cr3 : [esp + ]
	; estoy con el directorio de paginas del kernel
	mov edx, cr3
	mov eax, [esp] 
	mov cr3, eax
	; estoy con el directorio de paginas del arbitro

	mov ax, [fs:0]
	xor ah, 0x10
	;imprimo algo en pantalla
	mov [fs:0], ax

	mov cr3, edx
	; estoy con el directorio de paginas del kernel
	ret

print_asm:
    ; str*: [esp + 0]
    ; fila: [esp + 4]
    ; columna: [esp + 8]
    ; attr: [esp + 12]
    mov edi, [esp + 0]
    xor ecx, ecx
    .tam_loop:
    mov al, [edi + ecx]
    cmp al, 0
    inc ecx
    jne .tam_loop 
    ; ecx: tam string


    imprimir_texto_mp edi, ecx, 0x07, 0, 0

    ret

%include "a20.asm"

; definicion de variables

msg_primera_linea: db "TP 3 grupo : Rucula y parmesanos"
msg_primera_linea_len: equ $ - msg_primera_linea

msg_primera_linea_paging db		"TP 3 grupo : Rucula y parmesano (Paging on)"
msg_primera_linea_paging_len equ	$ - msg_primera_linea_paging

msg_ultima_linea: db "Laciana - Raposo - Santos"
msg_ultima_linea_len: equ $ - msg_ultima_linea


